﻿/******************************************************
 * author:Zhou Jiayi
 * date:20180108 10:28 +0800
 * E-mail:zjy_bjut@126.com
 * description: Use Newton iteration method to solve a quadratic equation.
 *****************************************************/
using System;
namespace NewtonIteration
{
    class Program
    {
        static void Main(string[] args)
        {
            //a,b,c分别为二次项、一次项、常数项系数
            double a = 0.00;
            double b = 0.00;
            double c = 0.00;
            //ep为迭代精度要求
            double ep = 0.00;
            //二元一次方程根的判别式
            double delta = 0.00;
            //x0为迭代初值
            double x0 = 0.00;
            double x00 = 0.00;
            double epk = 1.00;

            Console.WriteLine(" Please enter the parameters(a,b,c) of the quadratic equation(a*x^2+b*x+c=0)");
            Console.WriteLine(" Please enter the parameter 'a' : ");
            a = Convert.ToDouble(Console.ReadLine());
            Console.WriteLine(" a = " + a);//用户输入并显示，为系数a赋值

            Console.WriteLine(" Please enter the parameter 'b' : ");
            b = Convert.ToDouble(Console.ReadLine());
            Console.WriteLine(" b = " + b);//用户输入并显示，为系数b赋值

            Console.WriteLine(" Please enter the parameter 'c' : ");
            c = Convert.ToDouble(Console.ReadLine());
            Console.WriteLine(" c = " + c); //用户输入并显示，为系数c赋值

            Console.WriteLine(" The quadratic equation is :  " + a + "*x^2+" + b + "*x+" + c + "=0");  //显示方程



            Console.WriteLine(" Please enter the iterative initial value ‘x0’：");
            x0 = Convert.ToDouble(Console.ReadLine());
            Console.WriteLine(" x0 = " + x0); //用户输入并显示，设置迭代初值x


            Console.WriteLine(" Please enter the accuracy requirement ‘ep’：");
            ep = Convert.ToDouble(Console.ReadLine());
            Console.WriteLine(" ep = " + ep);//用户输入并显示，设置精度要求ep


            delta = b * b - 4 * a * c;//根的判别式


            //△<时，输出：方程无解。
            if (delta < 0)
            {
                Console.WriteLine(" There is no real solution to this equation. ");
                Console.ReadKey();
                Console.ReadLine();
            }
            else
            {
                if (delta.Equals(0)) //△<时,方程有两个重根，其根位于抛物线对称轴与x轴交点。
                {
                    x0 = -b / (2 * a);
                    Console.WriteLine(" 此方程有两个重根：x1=x2=" + x0);
                    Console.ReadKey();
                    Console.ReadLine();
                }
                else
                {
                    while (epk > ep)//△>时,方程有两个根，利用牛顿迭代法求解。
                    {
                        x00 = x0;
                        x0 = GetNextX(x0, a, b, c);
                        epk = x0 - x00;
                        epk = GetAbsOfNum(epk);
                    }
                    double x1 = x0;
                    double x2 = -b / a - x1;
                    Console.WriteLine(" 方程的两个根为：x1=" + x1 + "，x2=" + x2 + "。");
                    Console.ReadKey();
                    Console.ReadLine();
                }
            }
        }


        /// <summary>
        /// 此函数计算并返回函数fx的数值
        /// </summary>
        /// <param name="x">自变量</param>
        /// <param name="a">二次项系数</param>
        /// <param name="b">一次项系数</param>
        /// <param name="c">常数项</param>
        /// <returns>返回函数数值</returns>
        static double GetFxRealnum(double x, double a, double b, double c)                      //fx=ax²+bx+c=0；
        {
            double fx = (a * Math.Pow(x, 2) + b * x + c);
            return fx;
        }


        /// <summary>
        /// 此函数计算并返回fx的导数值
        /// </summary>
        /// <param name="x">自变量</param>
        /// <param name="a">二次项系数</param>
        /// <param name="b">一次项系数</param>
        /// <returns>导数数值</returns>
        static double GetDerivativeOfFx(double x, double a, double b)             //fx的一阶导：dfx=2ax+b
        {
            double dfx = (2 * a * x + b);
            return dfx;
        }


        /// <summary>
        /// 此函数利用牛顿迭代公式计算并返回下一个迭代值Xk+1
        /// </summary>
        /// <param name="Xk">本次迭代值</param>
        /// <param name="a">二次项系数</param>
        /// <param name="b">一次项系数</param>
        /// <param name="c">常数项</param>
        /// <returns>下一个迭代值Xk+1</returns>
        static double GetNextX(double Xk, double a, double b, double c)                  //牛顿迭代公式求Xk+1
        {
            double NextX = 0.00;
            NextX = Xk - GetFxRealnum(Xk, a, b, c) / GetDerivativeOfFx(Xk, a, b);
            return NextX;
        }


        /// <summary>
        /// 此函数计算并返回x的绝对值
        /// </summary>
        /// <param name="x">输入值</param>
        /// <returns>输入值的绝对值</returns>
        static double GetAbsOfNum(double x)//求绝对值
        {
            if (x < 0)
                return -x;
            else
                return x;
        }

    }

}